<!DOCTYPE html>
<html>
<head><meta name="generator" content="Hexo 3.8.0">
  <meta charset="utf-8">
  
  <title>Spring Security中的OAuth2功能 | gdme1320 的笔记</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta name="description" content="Table of Contents   调用堆栈：  Authentication :: 验证用户是否登录 Authorization :: 验证登录的用户是否有权限访问资源   Classes  TokenStore ClientDetailsService AuthorizationServerTokenService ResourceServerTokenServices 资源服务器读">
<meta property="og:type" content="article">
<meta property="og:title" content="Spring Security中的OAuth2功能">
<meta property="og:url" content="http://gdme1320.gitee.com/java/spring-security/oauth/index.html">
<meta property="og:site_name" content="gdme1320 的笔记">
<meta property="og:description" content="Table of Contents   调用堆栈：  Authentication :: 验证用户是否登录 Authorization :: 验证登录的用户是否有权限访问资源   Classes  TokenStore ClientDetailsService AuthorizationServerTokenService ResourceServerTokenServices 资源服务器读">
<meta property="og:locale" content="default">
<meta property="og:image" content="http://gdme1320.gitee.com/java/spring-security/oauth/.ouath/jwt-classes.png">
<meta property="og:updated_time" content="2022-03-23T09:59:37.415Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Spring Security中的OAuth2功能">
<meta name="twitter:description" content="Table of Contents   调用堆栈：  Authentication :: 验证用户是否登录 Authorization :: 验证登录的用户是否有权限访问资源   Classes  TokenStore ClientDetailsService AuthorizationServerTokenService ResourceServerTokenServices 资源服务器读">
<meta name="twitter:image" content="http://gdme1320.gitee.com/java/spring-security/oauth/.ouath/jwt-classes.png">
  
    <link rel="alternate" href="/atom.xml" title="gdme1320 的笔记" type="application/atom+xml">
  
  
  
    <link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
  

  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">

  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" integrity="sha384-XdYbMnZ/QjLh6iI4ogqCTaIjrFk87ip+ekIjefZch0Y+PvJ8CDYtEs1ipDmPorQ+" crossorigin="anonymous">

  <link rel="stylesheet" href="/css/styles.css">
  <link rel="stylesheet" href="/css/docs.min.css">
  

</head>
</html>
<body>
  <nav class="navbar navbar-inverse">
  <div class="container">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#main-menu-navbar" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="main-menu-navbar">
      <ul class="nav navbar-nav">
        
          <li><a class href="/index.html">Home</a></li>
        
          <li><a class href="/archives/">Archives</a></li>
        
      </ul>

      <!--
      <ul class="nav navbar-nav navbar-right">
        
          <li><a href="/atom.xml" title="RSS Feed"><i class="fa fa-rss"></i></a></li>
        
      </ul>
      -->
    </div><!-- /.navbar-collapse -->
  </div><!-- /.container-fluid -->
</nav>

  <div class="container bs-docs-container">
  
    <div class="row">
        <div class="col-sm-8 blog-main">
          <article id="post-java/spring-security/oauth" class="article article-type-post" itemscope itemprop="blogPost">

  <header class="article-header">
    
  
    <h1 class="article-title" itemprop="name">
      Spring Security中的OAuth2功能
    </h1>
  


  </header>

  <div class="article-meta">
    <div class="article-datetime">
  <a href="/java/spring-security/oauth/" class="article-date"><time datetime="2022-03-23T09:59:37.415Z" itemprop="datePublished">2022-03-23</time></a>
</div>

    
    
  <div class="article-category">
    <a class="article-category-link" href="/categories/java/">java</a> / <a class="article-category-link" href="/categories/java/spring-security/">spring-security</a>
  </div>


  </div>
  <div class="article-inner">

    <div class="article-entry" itemprop="articleBody">
      
        
<div id="content">
<div id="table-of-contents">
<h2>Table of Contents</h2>
<div id="text-table-of-contents">
<ul>
<li><a href="#org21426ef">调用堆栈：</a>
<ul>
<li><a href="#orga0923f4">Authentication :: 验证用户是否登录</a></li>
<li><a href="#orgd0adf7a">Authorization :: 验证登录的用户是否有权限访问资源</a></li>
</ul>
</li>
<li><a href="#org8349583">Classes</a>
<ul>
<li><a href="#org78a2809">TokenStore</a></li>
<li><a href="#org3ec2a29">ClientDetailsService</a></li>
<li><a href="#org1fc1e79">AuthorizationServerTokenService</a></li>
<li><a href="#org41f72b5">ResourceServerTokenServices 资源服务器读取Token的接口</a>
<ul>
<li><a href="#orgb23d827">实现类：</a></li>
</ul>
</li>
<li><a href="#orgd267aac">TokenEnhancer</a></li>
<li><a href="#org5254a4c">AccessTokenConverter</a></li>
</ul>
</li>
<li><a href="#orge2942de">OAuth2 Server Config 授权服务器的配置</a>
<ul>
<li><a href="#org1a8a571">void configure(AuthorizationServerSecurityConfigurer)</a></li>
<li><a href="#org5bc9fad">void configure(AuthorizationServerEndpointsConfigurer)</a></li>
<li><a href="#org2b9782f">void configure(ClientDetailsServiceConfigurer)</a></li>
</ul>
</li>
<li><a href="#org739daad">OAuth2 Resource Config 资源服务器配置</a></li>
<li><a href="#org42e8163">Spring OAuth2 and JWT</a>
<ul>
<li><a href="#org4e618db">Jwt OAuth2 Authorization Server Config</a></li>
<li><a href="#orgf8f8687">Jwt OAuth2 Resource Server Config</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div class="outline-2" id="outline-container-org21426ef">
<h2 id="org21426ef">调用堆栈：</h2>
<div class="outline-text-2" id="text-org21426ef">
</div>
<div class="outline-3" id="outline-container-orga0923f4">
<h3 id="orga0923f4">Authentication :: 验证用户是否登录</h3>
<div class="outline-text-3" id="text-orga0923f4">
<pre class="example">
# 调用ResourceServerTokenServices#loadAuthentication（实现类不一定是DefaultTokenServices）
loadAuthentication:229, DefaultTokenServices (org.springframework.security.oauth2.provider.token)
authenticate:83, OAuth2AuthenticationManager (org.springframework.security.oauth2.provider.authentication)
doFilter:150, OAuth2AuthenticationProcessingFilter (org.springframework.security.oauth2.provider.authentication)
</pre>
</div>
</div>
<div class="outline-3" id="outline-container-orgd0adf7a">
<h3 id="orgd0adf7a">Authorization :: 验证登录的用户是否有权限访问资源</h3>
<div class="outline-text-3" id="text-orgd0adf7a">
<p>
AbstractSecurityInterceptor 
this.accessDecisionManager.decide(authenticated, object, attributes);
</p>
</div>
</div>
</div>
<div class="outline-2" id="outline-container-org8349583">
<h2 id="org8349583">Classes</h2>
<div class="outline-text-2" id="text-org8349583">
</div>
<div class="outline-3" id="outline-container-org78a2809">
<h3 id="org78a2809">TokenStore</h3>
<div class="outline-text-3" id="text-org78a2809">
<p>
这个接口中的方式用于对OAuth2 Token的保存与读取，例如：
</p>
<ul class="org-ul">
<li>void storeAccessToken(OAuth2AccessToken, OAuth2Authentication) 保存</li>
<li>void removeAccessToken(OAuth2AccessToken) 从数据源中移除AccessToken</li>
</ul>
</div>
</div>
<div class="outline-3" id="outline-container-org3ec2a29">
<h3 id="org3ec2a29">ClientDetailsService</h3>
<div class="outline-text-3" id="text-org3ec2a29">
<p>
这个接口中只有一个方法，就是根据ClientID加载Client的信息。
这里的Client在OAuth2中就是客户端程序，面不是用户终端。ClientDetails包括ClientSecret,Scope等。
</p>
</div>
</div>
<div class="outline-3" id="outline-container-org1fc1e79">
<h3 id="org1fc1e79">AuthorizationServerTokenService</h3>
<div class="outline-text-3" id="text-org1fc1e79">
<p>
这个就是OAuth2中进行AccessToken创建的接口。包含三个方法，
</p>
<ul class="org-ul">
<li>OAuth2AccessToken createAccessToken(OAuth2Authentication) 根据传递的凭据，创建AccessToken</li>
<li>OAuth2AccessToken refreshAccessToken(refreshToken, TokenRequest) OAuth2中的refreshToken机制，作用refreshToken交换新的AccessToken时被调用</li>
<li>OAuth2AccessToken getAccessToken(OAuth2Authentication) 如果Authentication对应的AccessToken存在则返回</li>
</ul>
</div>
</div>
<div class="outline-3" id="outline-container-org41f72b5">
<h3 id="org41f72b5">ResourceServerTokenServices 资源服务器读取Token的接口</h3>
<div class="outline-text-3" id="text-org41f72b5">
<p>
包含两个方法
</p>
<ol class="org-ol">
<li>loadAuthentication 从token字符串读取Authentication</li>
<li>readAccessToken 从token字符串读取Access</li>
</ol>
</div>
<div class="outline-4" id="outline-container-orgb23d827">
<h4 id="orgb23d827">实现类：</h4>
<div class="outline-text-4" id="text-orgb23d827">
<ul class="org-ul">
<li>DefaultTokenServices: 需要一个TokenStore，实际是从TokenStore读取。这个类也是AuthorizationServerTokenServices的默认实现</li>
<li>UserInfoTokenServices: 从远端服务器（授权服务器）读取Token。</li>
<li>RemoteTokenServices: 也是通过远端服务器读取Token，与UserInfoTokenServices类似，内部发出的HTTP请求不同</li>
</ul>
<p>
ResourceServerTokenServicesConfiguration类中包含有自动配置这些类的逻辑：
</p>
<ul class="org-ul">
<li>UserInfoTokenService: NotTokenInfoCondition</li>
</ul>
<p>
Conditions:
</p>
<ul class="org-ul">
<li>TokenInfoCondition: Match if (or)
<ul class="org-ul">
<li>security.oauth2.resource.token-info-uri 和 security.oauth2.resource.user-info-uri都没有配置时</li>
<li>security.oauth2.resource.token-info-uri有值且security.oauth2.resource.prefer-token-info=true时</li>
</ul></li>
<li>NotTokenInfoCondition: !TokenInfoCondition</li>
</ul>
</div>
</div>
</div>
<div class="outline-3" id="outline-container-orgd267aac">
<h3 id="orgd267aac">TokenEnhancer</h3>
<div class="outline-text-3" id="text-orgd267aac">
<p>
在AccessToken被AuthorizationServerTokenService存储之前，对AceessToken进行修改。
这个接口只包含一个方法，传递OAuth2AccessToken &amp; OAuth2Authentication，实现方法进行修改，然后将修改后的AccessToken返回。
</p>
</div>
</div>
<div class="outline-3" id="outline-container-org5254a4c">
<h3 id="org5254a4c">AccessTokenConverter</h3>
<div class="outline-text-3" id="text-org5254a4c">
<p>
网络上传递的token是以字符串的形式，程序内当然是用对象表示方便。这个接口中提供了string, map, AccessToken对象之间的转换方法。
</p>
</div>
</div>
</div>
<div class="outline-2" id="outline-container-orge2942de">
<h2 id="orge2942de">OAuth2 Server Config 授权服务器的配置</h2>
<div class="outline-text-2" id="text-orge2942de">
<p>
项目中引用了Spring-Security-OAuth2之后，通过继承  AuthorizationServerConfigurerAdapter  ，来自定义配置OAuth2 Server。
</p>
<div class="org-src-container">
<pre class="src src-java"><span style="font-weight: bold; text-decoration: underline;">@Configuration</span>
<span style="font-weight: bold; text-decoration: underline;">@EnableAuthorizationServer</span>
<span style="font-weight: bold;">public</span> <span style="font-weight: bold;">class</span> <span style="font-weight: bold; text-decoration: underline;">OAuth2ServerConfig</span> <span style="font-weight: bold;">extends</span> <span style="font-weight: bold; text-decoration: underline;">AuthorizationServerConfigurerAdapter</span> {

    <span style="font-style: italic;">/**</span>
<span style="font-style: italic;">     * 对endpoint的自定义配置</span>
<span style="font-style: italic;">     */</span>
    <span style="font-weight: bold;">public</span> <span style="font-weight: bold; text-decoration: underline;">void</span> <span style="font-weight: bold;">configure</span>(<span style="font-weight: bold; text-decoration: underline;">AuthorizationServerEndpointsConfigurer</span> <span style="font-weight: bold; font-style: italic;">endpoints</span>);




}
</pre>
</div>
<p>
注解  EnableAuthorizationServer  用于开启OAuth2Server的功能。开启后，应用程序新增了几个EndPoint：例如
</p>
<ul class="org-ul">
<li>/oauth/authorize</li>
<li>/oauth/token</li>
<li>/oauth/check_token</li>
<li>/oauth/confirm_access</li>
<li>/oauth/error</li>
</ul>
<p>
对应着OAuth2各流程。
这个类中有几个方法能够被重写：
</p>
</div>
<div class="outline-3" id="outline-container-org1a8a571">
<h3 id="org1a8a571">void configure(AuthorizationServerSecurityConfigurer)</h3>
</div>
<div class="outline-3" id="outline-container-org5bc9fad">
<h3 id="org5bc9fad">void configure(AuthorizationServerEndpointsConfigurer)</h3>
<div class="outline-text-3" id="text-org5bc9fad">
<p>
在这个方法中，能够自定义 tokenStore，accessTokenConverter, tokenEnhancer, userDetailsService, authenticationManager等。
如果不重写这个方法，则框架创建默认的配置（AuthorizationServerEndpointsConfigurer.createDefault*），一般默认配置足够，配置Jwt支持的时候，会要重写这个方法。
</p>
</div>
</div>
<div class="outline-3" id="outline-container-org2b9782f">
<h3 id="org2b9782f">void configure(ClientDetailsServiceConfigurer)</h3>
<div class="outline-text-3" id="text-org2b9782f">
<p>
重写这个方法，自定义配置 ClientDetailsService。例如：
</p>
<ul class="org-ul">
<li>使用 方法参数给的ClientDetailsServiceConfigurer对象提供的流式API，将clients的信息保存在内存中</li>
<li>自己继承 ClientDetailsService，实现从自己的数据源中读取client的信息。</li>
</ul>
</div>
</div>
</div>
<div class="outline-2" id="outline-container-org739daad">
<h2 id="org739daad">OAuth2 Resource Config 资源服务器配置</h2>
<div class="outline-text-2" id="text-org739daad">
<p>
通过  EnableResourceServer  开启ResourceServer功能。通过继承  ResourceServerConfigurerAdapter  自定义 Resource Server的配置。
</p>
<div class="org-src-container">
<pre class="src src-java"><span style="font-weight: bold; text-decoration: underline;">@EnableResourceServer</span>
<span style="font-weight: bold;">public</span> <span style="font-weight: bold; text-decoration: underline;">void</span> <span style="font-weight: bold; font-style: italic;">OAuth2ResourceServerConfig</span> <span style="font-weight: bold;">extends</span> <span style="font-weight: bold; text-decoration: underline;">ResourceServerConfigurerAdapter</span> {

    <span style="font-weight: bold; text-decoration: underline;">void</span> <span style="font-weight: bold;">configure</span>(<span style="font-weight: bold; text-decoration: underline;">ResourceServerSecurityConfigurer</span>);


}
</pre>
</div>
</div>
</div>
<div class="outline-2" id="outline-container-org42e8163">
<h2 id="org42e8163">Spring OAuth2 and JWT</h2>
<div class="outline-text-2" id="text-org42e8163">
<p>
Jwt的AccessToken不需要存储到数据源中，所有信息都包含在token字符串里面了。但是它需要反序列化，并且验证签名。
Spring提供了  JwtAccessTokenConverter   JwtTokenStore 
</p>
<div class="figure">
<p><img alt="jwt-classes.png" src=".ouath/jwt-classes.png">
</p>
</div>
<p>
JwtAccessTokenConverter内部有一个AccessTokenConverter（默认是DefaultAccessTokenConverter），实现AccessTokenConverter接口都是通过调用内部的那个对象。
实现TokenEnhancer接口是做一些jwt相关的操作。
它还包括反序列化、验证命名的方法，这些方法被JwtTokenStore使用。
</p>
<p>
JwtTokenStore内部Store的方法为空，因为Jwt不需要存储到数据源中。Read的方法，通过内部的JwtAccessTokenConverter对象，进行字符串token与AccessToken对象之间的转化。
</p>
</div>
<div class="outline-3" id="outline-container-org4e618db">
<h3 id="org4e618db">Jwt OAuth2 Authorization Server Config</h3>
<div class="outline-text-3" id="text-org4e618db">
<p>
配置Oauth2认证服务器支持jwt，入口仍然是  AuthorizationServerConfigurerAdapter  ，需要将 JwtTokenStore 和 JwtTokenConverter 替换掉默认的配置。
</p>
<div class="org-src-container">
<pre class="src src-java">
<span style="font-weight: bold; text-decoration: underline;">@Configuration</span>
<span style="font-weight: bold; text-decoration: underline;">@EnalbeAuthorizationServer</span>
<span style="font-weight: bold;">public</span> <span style="font-weight: bold;">class</span> <span style="font-weight: bold; text-decoration: underline;">OAuthServerConfig</span> <span style="font-weight: bold;">extends</span> <span style="font-weight: bold; text-decoration: underline;">AuthorizationServerConfigurerAdapter</span> {

    <span style="font-weight: bold; text-decoration: underline;">@Bean</span>
    <span style="font-weight: bold;">public</span> <span style="font-weight: bold; text-decoration: underline;">TokenStore</span> <span style="font-weight: bold;">tokenStore</span>() {
        <span style="font-weight: bold; font-style: italic;">// </span><span style="font-weight: bold; font-style: italic;">create JwtTokenStore()</span>
    }

    <span style="font-weight: bold; text-decoration: underline;">@Bean</span>
    <span style="font-weight: bold;">public</span> <span style="font-weight: bold; text-decoration: underline;">JwtAccessTokenConverter</span> <span style="font-weight: bold;">accessTokenConverter</span>() {
        <span style="font-weight: bold; font-style: italic;">// </span><span style="font-weight: bold; font-style: italic;">create object JwtAccessTokenConverter</span>
        <span style="font-weight: bold; font-style: italic;">// </span><span style="font-weight: bold; font-style: italic;">JwtAccessTokenConverter 既是TokenConverter，也是TokenEnhancer，声明为Bean，而且是单例模式的。</span>
        <span style="font-weight: bold; text-decoration: underline;">var</span> <span style="font-weight: bold; font-style: italic;">retn</span> = <span style="font-weight: bold;">new</span> <span style="font-weight: bold; text-decoration: underline;">JwtAccessTokenConverter</span>();
        <span style="font-weight: bold; font-style: italic;">// </span><span style="font-weight: bold; font-style: italic;">配置 JwtAccessTokenConverter</span>
        <span style="font-weight: bold; font-style: italic;">// </span><span style="font-weight: bold; font-style: italic;">retn.setKeyPair() 这个方法设置认证签名时作用的密钥</span>
        <span style="font-weight: bold; font-style: italic;">// </span><span style="font-weight: bold; font-style: italic;">不要忘记调用JwtAccessTokenConverter.afterPropertiesSet()方法，这里因为声明成了bean，spring框架会调用这个方法。</span>
        <span style="font-weight: bold;">return</span> retn;
    }

    <span style="font-weight: bold; text-decoration: underline;">@Override</span>
    <span style="font-weight: bold;">public</span> <span style="font-weight: bold; text-decoration: underline;">void</span> <span style="font-weight: bold;">configure</span>(<span style="font-weight: bold; text-decoration: underline;">AuthorizationServerEndpointsConfigurer</span> <span style="font-weight: bold; font-style: italic;">endpoints</span>) {
        endpoints.tokenStore(tokenStore()) <span style="font-weight: bold; font-style: italic;">// </span><span style="font-weight: bold; font-style: italic;">使用上面创建的TokenStore bean</span>
            .accessTokenConverter(accessTokenConverter()) <span style="font-weight: bold; font-style: italic;">// </span><span style="font-weight: bold; font-style: italic;">无论是配置accessTokenConverter还是tokenEnhancer，都使用的那一个bean</span>
            .tokenEnhancer(accessTokenConverter())
            <span style="font-weight: bold; font-style: italic;">// </span><span style="font-weight: bold; font-style: italic;">框架提供了另外一个名为TokenEnhancerChain人类，也实现了TokenEnhancer，它里边包含了TokenEnhancer的列表，调用它的enhance方法时，列表中所有的enhancer方法都被调用</span>
            <span style="font-weight: bold; font-style: italic;">// </span><span style="font-weight: bold; font-style: italic;">当希望自定义生成的AccessToken时，构造这个类，然后把默认的TokenEnhancer和自己的TokenEnhancer实现传递给它</span>
             ...
     }
 }
</pre>
</div>
</div>
</div>
<div class="outline-3" id="outline-container-orgf8f8687">
<h3 id="orgf8f8687">Jwt OAuth2 Resource Server Config</h3>
<div class="outline-text-3" id="text-orgf8f8687">
<div class="org-src-container">
<pre class="src src-java"><span style="font-weight: bold; text-decoration: underline;">@Configuration</span>
<span style="font-weight: bold; text-decoration: underline;">@EnableResourceServer</span>
<span style="font-weight: bold;">public</span> <span style="font-weight: bold; text-decoration: underline;">ResourceServerConfig</span> <span style="font-weight: bold;">extends</span> <span style="font-weight: bold; text-decoration: underline;">ResourceServerConfigurerAdapter</span> {

    <span style="font-weight: bold; text-decoration: underline;">DefaultTokenServices</span> <span style="font-weight: bold;">resourceServerTokenServices</span>() {
        <span style="font-weight: bold; font-style: italic;">// </span><span style="font-weight: bold; font-style: italic;">创建JwtAccessTokenConverter</span>
        <span style="font-weight: bold; text-decoration: underline;">var</span> <span style="font-weight: bold; font-style: italic;">converter</span> = <span style="font-weight: bold;">new</span> <span style="font-weight: bold; text-decoration: underline;">JwtAccessTokenConverter</span>();
        converter.setVerifierKey(key); <span style="font-weight: bold; font-style: italic;">// </span><span style="font-weight: bold; font-style: italic;">设置验证token是使用的密钥。</span>
        converter.afterPropertiesSet();
        <span style="font-weight: bold; font-style: italic;">// </span><span style="font-weight: bold; font-style: italic;">创建TokenStore</span>
        <span style="font-weight: bold; text-decoration: underline;">var</span> <span style="font-weight: bold; font-style: italic;">tokenStore</span> = <span style="font-weight: bold;">new</span> <span style="font-weight: bold; text-decoration: underline;">JwtTokenStore</span>(conveter);
        <span style="font-weight: bold; font-style: italic;">// </span><span style="font-weight: bold; font-style: italic;">创建TokenService</span>
        <span style="font-weight: bold; text-decoration: underline;">var</span> <span style="font-weight: bold; font-style: italic;">retn</span> = <span style="font-weight: bold;">new</span> <span style="font-weight: bold; text-decoration: underline;">DefaultTokenServices</span>();
        tokenService.setTokenStore(tokenStore);
        <span style="font-weight: bold;">return</span> retn;
    }

    <span style="font-weight: bold; text-decoration: underline;">@Override</span>
        <span style="font-weight: bold;">public</span> <span style="font-weight: bold; text-decoration: underline;">void</span> <span style="font-weight: bold;">configurer</span>(<span style="font-weight: bold; text-decoration: underline;">ResourceServerSecurityConfigurer</span> <span style="font-weight: bold; font-style: italic;">resources</span>) {
        <span style="font-weight: bold; text-decoration: underline;">var</span> <span style="font-weight: bold; font-style: italic;">tokenService</span> = resourceServerTokenServices();
        resources.tokenSerivces(tokenService);
    }


</pre>
</div>
</div>
</div>
</div>
</div>
<div class="status" id="postamble">
<p class="author">Author: gdme1320</p>
<p class="validation"><a href="http://validator.w3.org/check?uri=referer" target="_blank" rel="noopener">Validate</a></p>
</div>

      
    </div>

    
      

    

    <footer class="article-footer">
      <a data-url="http://gdme1320.gitee.com/java/spring-security/oauth/" data-id="cl13eo7mv00ewhjv4nizxxvsn" class="article-share-link">
        <i class="fa fa-share"></i> Share
      </a>
      
      

    </footer>
  </div>
  
    
<ul id="article-nav" class="nav nav-pills nav-justified">
  
  <li role="presentation">
    <a href="/java/spring-jpa/native-query-to-pojo/" id="article-nav-older" class="article-nav-link-wrap">
      <i class="fa fa-chevron-left pull-left"></i>
      <span class="article-nav-link-title">Native Query Result to POJO</span>
    </a>
  </li>
  
  
  <li role="presentation">
    <a href="/java/shiro/class/" id="article-nav-newer" class="article-nav-link-wrap">
      <span class="article-nav-link-title">‎</span>
      <i class="fa fa-chevron-right pull-right"></i>
    </a>
  </li>
  
</ul>


  
</article>




        </div>
        <div class="col-sm-3 col-sm-offset-1 blog-sidebar">
          
  
  <div class="sidebar-module">
    <h4>Categories</h4>
    <ul class="sidebar-module-list"><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/apps/">apps</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/architecture/">architecture</a><span class="sidebar-module-list-count">2</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/devops/">devops</a><span class="sidebar-module-list-count">10</span><ul class="sidebar-module-list-child"><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/devops/kubectl/">kubectl</a><span class="sidebar-module-list-count">2</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/devops/kubernetes/">kubernetes</a><span class="sidebar-module-list-count">3</span></li></ul></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/dotnet/">dotnet</a><span class="sidebar-module-list-count">3</span><ul class="sidebar-module-list-child"><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/dotnet/entityframework/">entityframework</a><span class="sidebar-module-list-count">1</span></li></ul></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/elasticsearch/">elasticsearch</a><span class="sidebar-module-list-count">4</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/emacs/">emacs</a><span class="sidebar-module-list-count">4</span><ul class="sidebar-module-list-child"><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/emacs/org-mode/">org-mode</a><span class="sidebar-module-list-count">3</span></li></ul></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/git/">git</a><span class="sidebar-module-list-count">2</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/graphql/">graphql</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/groovy/">groovy</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/java/">java</a><span class="sidebar-module-list-count">52</span><ul class="sidebar-module-list-child"><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/java/concurrent/">concurrent</a><span class="sidebar-module-list-count">4</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/java/jackson/">jackson</a><span class="sidebar-module-list-count">2</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/java/shiro/">shiro</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/java/spring/">spring</a><span class="sidebar-module-list-count">11</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/java/spring-amqp/">spring-amqp</a><span class="sidebar-module-list-count">5</span><ul class="sidebar-module-list-child"><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/java/spring-amqp/spring-jpa/">spring-jpa</a><span class="sidebar-module-list-count">1</span></li></ul></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/java/spring-jpa/">spring-jpa</a><span class="sidebar-module-list-count">10</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/java/spring-security/">spring-security</a><span class="sidebar-module-list-count">3</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/java/thymeleaf/">thymeleaf</a><span class="sidebar-module-list-count">2</span><ul class="sidebar-module-list-child"><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/java/thymeleaf/maven/">maven</a><span class="sidebar-module-list-count">1</span></li></ul></li></ul></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/jenkins/">jenkins</a><span class="sidebar-module-list-count">3</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/journal/">journal</a><span class="sidebar-module-list-count">7</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/js/">js</a><span class="sidebar-module-list-count">3</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/linux/">linux</a><span class="sidebar-module-list-count">35</span><ul class="sidebar-module-list-child"><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/linux/kde/">kde</a><span class="sidebar-module-list-count">2</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/linux/kross/">kross</a><span class="sidebar-module-list-count">3</span><ul class="sidebar-module-list-child"><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/linux/kross/ktorrent-scripts/">ktorrent-scripts</a><span class="sidebar-module-list-count">1</span></li></ul></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/linux/shell/">shell</a><span class="sidebar-module-list-count">6</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/linux/tcp/">tcp</a><span class="sidebar-module-list-count">1</span></li></ul></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/lisp/">lisp</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/mongodb/">mongodb</a><span class="sidebar-module-list-count">2</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/mssql/">mssql</a><span class="sidebar-module-list-count">3</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/mysql/">mysql</a><span class="sidebar-module-list-count">12</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/nginx/">nginx</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/node/">node</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/postgresql/">postgresql</a><span class="sidebar-module-list-count">2</span><ul class="sidebar-module-list-child"><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/postgresql/client/">client</a><span class="sidebar-module-list-count">1</span></li></ul></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/python/">python</a><span class="sidebar-module-list-count">19</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/regex/">regex</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/rfc/">rfc</a><span class="sidebar-module-list-count">2</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/vim/">vim</a><span class="sidebar-module-list-count">3</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/categories/windows/">windows</a><span class="sidebar-module-list-count">7</span></li></ul>
  </div>



  
  <div class="sidebar-module">
    <h4>Tags</h4>
    <ul class="sidebar-module-list"><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/tags/ReentrantLock/">ReentrantLock</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/tags/nohup/">nohup</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/tags/pandoc/">pandoc</a><span class="sidebar-module-list-count">1</span></li></ul>
  </div>



  
  <div class="sidebar-module">
    <h4>Tag Cloud</h4>
    <p class="tagcloud">
      <a href="/tags/ReentrantLock/" style="font-size: 10px;">ReentrantLock</a> <a href="/tags/nohup/" style="font-size: 10px;">nohup</a> <a href="/tags/pandoc/" style="font-size: 10px;">pandoc</a>
    </p>
  </div>


  
  <div class="sidebar-module">
    <h4>Archives</h4>
    <ul class="sidebar-module-list"><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2919/06/">June 2919</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2022/03/">March 2022</a><span class="sidebar-module-list-count">58</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2022/01/">January 2022</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2021/11/">November 2021</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2021/10/">October 2021</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2021/04/">April 2021</a><span class="sidebar-module-list-count">2</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2021/03/">March 2021</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2021/02/">February 2021</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2021/01/">January 2021</a><span class="sidebar-module-list-count">2</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2020/12/">December 2020</a><span class="sidebar-module-list-count">2</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2020/11/">November 2020</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2020/10/">October 2020</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2020/09/">September 2020</a><span class="sidebar-module-list-count">3</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2020/07/">July 2020</a><span class="sidebar-module-list-count">3</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2020/06/">June 2020</a><span class="sidebar-module-list-count">10</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2020/04/">April 2020</a><span class="sidebar-module-list-count">4</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2020/03/">March 2020</a><span class="sidebar-module-list-count">8</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2020/02/">February 2020</a><span class="sidebar-module-list-count">4</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2020/01/">January 2020</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2019/12/">December 2019</a><span class="sidebar-module-list-count">7</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2019/11/">November 2019</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2019/10/">October 2019</a><span class="sidebar-module-list-count">11</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2019/09/">September 2019</a><span class="sidebar-module-list-count">6</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2019/08/">August 2019</a><span class="sidebar-module-list-count">4</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2019/07/">July 2019</a><span class="sidebar-module-list-count">10</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2019/06/">June 2019</a><span class="sidebar-module-list-count">3</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2019/05/">May 2019</a><span class="sidebar-module-list-count">3</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2019/04/">April 2019</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2019/03/">March 2019</a><span class="sidebar-module-list-count">8</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2019/02/">February 2019</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2019/01/">January 2019</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2018/11/">November 2018</a><span class="sidebar-module-list-count">4</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2018/10/">October 2018</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2018/08/">August 2018</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2018/07/">July 2018</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2018/06/">June 2018</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2018/03/">March 2018</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2017/07/">July 2017</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2017/06/">June 2017</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2017/04/">April 2017</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/2015/05/">May 2015</a><span class="sidebar-module-list-count">1</span></li><li class="sidebar-module-list-item"><a class="sidebar-module-list-link" href="/archives/1970/01/">January 1970</a><span class="sidebar-module-list-count">9</span></li></ul>
  </div>



  
  <div class="sidebar-module">
    <h4>Recents</h4>
    <ul class="sidebar-module-list">
      
        <li>
          <a href="/java/acessing-generic-types-at-runtime/">获取泛型类型</a>
        </li>
      
        <li>
          <a href="/linux/shell/bash_cgi/">Script for Shell Parsing Parameters</a>
        </li>
      
        <li>
          <a href="/linux/shell/shell-script/">Shell Script Getting Start</a>
        </li>
      
        <li>
          <a href="/linux/tcp/network-tcp-performance-turning-with-sysctl/">【翻译】Sysctl调节Linux网络性能</a>
        </li>
      
        <li>
          <a href="/java/concurrent/aqs-src/">AQS源码笔记</a>
        </li>
      
    </ul>
  </div>



        </div>
    </div>
  </div>
  <footer class="blog-footer">
  <div class="container">
    <div id="footer-info" class="inner">
      &copy; 2022 gdme1320<br>
      Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>

  

<!-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" integrity="sha384-8gBf6Y4YYq7Jx97PIqmTwLPin4hxIzQw5aDmUg/DDhul9fFpbbLcLh3nTIIDJKhx" crossorigin="anonymous"></script> -->

<script src="/js/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>



<script src="/js/script.js"></script>

</body>
</html>
